package com.sleep.ws.server;

import com.sleep.ws.server.domain.WsServerProperties;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

public class WsServer {

    private static final Logger log = LoggerFactory.getLogger(WsServer.class);

    private final EventLoopGroup bossGroup = new NioEventLoopGroup();

    private final EventLoopGroup workerGroup = new NioEventLoopGroup();

    private Channel channel;

    private final String keyStore;

    private final String password;

    private final String path;

    public WsServer(WsServerProperties nettyServerProperties) {
        this.path = nettyServerProperties.getPath();
        this.keyStore = nettyServerProperties.getKeyStore();
        this.password = nettyServerProperties.getKeyStorePassword();
    }

    /**
     * 启动服务
     */
    public ChannelFuture run(InetSocketAddress address) {
        ChannelFuture f = null;
        try {
            ServerBootstrap b = new ServerBootstrap();
            WsServerChannelInitializer wsServerChannelInitializer = new WsServerChannelInitializer();
            wsServerChannelInitializer.setSslKeyStore(keyStore);
            wsServerChannelInitializer.setSslPassWord(password);
            wsServerChannelInitializer.setPath(path);
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(wsServerChannelInitializer);
            f = b.bind(address).sync();
            channel = f.channel();
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if (f != null && f.isSuccess()) {
                log.info("Netty server listening " + address.getHostName() + " on port " + address.getPort() + " and ready for connections...");
            } else {
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();
            }
        }

        return f;
    }

    public void destroy() {
        log.info("Shutdown Netty Server...");
        if (channel != null) {
            channel.close();
        }
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
        log.info("Shutdown Netty Server Success!");
    }
}
